﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Text.RegularExpressions;

namespace NczControlLibrary.Controls {
    [TemplateVisualState(GroupName = "rightmune", Name = "show"),
    TemplateVisualState(GroupName = "rightmune", Name = "hide"),
    TemplatePart(Name = "root", Type = typeof(Grid))]
    public class NczEditor : RichTextBox {
        enum MyState {
            show, hide, Normal, MouseOver, Disabled, ReadOnly, Focused, Unfocused
        }
        public NczEditor() {
            this.KeyDown += RichTxtBox_KeyDown;
            this.KeyUp += RichTxtBox_KeyUp;
            //
            this.keywordstore = new Dictionary<string, Brush>();
            this.FontSize = 12;
            //state
            DefaultStyleKey = typeof(NczEditor);
        }
        Grid root; Popup pop;
        public override void OnApplyTemplate() {
            root = GetTemplateChild("root") as Grid;
            root.MouseRightButtonDown += root_MouseRightButtonDown;
            pop = root.FindName("pop") as Popup;
            root.MouseLeftButtonDown += root_MouseLeftButtonDown;
            base.OnApplyTemplate();
        }

        void root_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            VisualStateManager.GoToState(this, MyState.hide.ToString(), false);
        }

        void root_MouseRightButtonDown(object sender, MouseButtonEventArgs e) {
            VisualStateManager.GoToState(this, MyState.show.ToString(), false);
            var pos = e.GetPosition(root);
            pop.HorizontalOffset = pos.X;
            pop.VerticalOffset = pos.Y;
            e.Handled = true;
        }
        bool shape_key_downup = true;
        void RichTxtBox_KeyUp(object sender, KeyEventArgs e) {
            var key = ((char)e.PlatformKeyCode).ToString();
            if (shape_key_downup = checkmarks.Contains(key)) {
                KeywordEffect();
            } else if (e.Key == Key.Back) {
                //KeywordBackspaceProcdrue();
            }
            //var tp = GetPositionFromPoint(cursor);
            //var tp2 = tp;
            //while (tp != null) {
            //    tp = tp.GetNextInsertionPosition(LogicalDirection.Forward);
            //    if (tp != null) {
            //        tp2 = tp;
            //    }
            //}
            //Selection.Select(tp2, tp2);
        }

        void RichTxtBox_KeyDown(object sender, KeyEventArgs e) {
            //var key = ((char)e.PlatformKeyCode).ToString();
            //if (shape_key_downup=checkmarks.Contains(key)) {
            //var p = Selection.End.GetCharacterRect(LogicalDirection.Forward);
            //cursor = new Point(p.X, p.Y);
            //}
        }
        //http://msdn.microsoft.com/zh-cn/library/system.windows.documents.textpointer(v=vs.95).aspx
        #region rich text box the code from msdn example,some repair
        TextPointer currentPointer;
        void KeywordEffect() {
            //TextPointer EndofContent = ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            var dir = LogicalDirection.Backward;
            var current = currentPointer;
            if (current == null)
                return;
            var current2 = current.GetPositionAtOffset(-keywordmaxlen, dir);
            this.Selection.Select(current, current2);
            var str = Selection.Text;
            var word = str.Split(checkmarks, StringSplitOptions.RemoveEmptyEntries).Last();
            current = currentPointer.GetPositionAtOffset(-word.Length, dir);
            Selection.Select(current, currentPointer);
            if (keywordstore.ContainsKey(word))
                Selection.ApplyPropertyValue(Run.ForegroundProperty, keywordstore[word] ?? new SolidColorBrush(Colors.Black));
        }
        string GetCurrentChar(TextPointer pointer, LogicalDirection direction) {
            TextPointer nextPointer = pointer.GetNextInsertionPosition(direction);
            if (nextPointer != null) {
                Selection.Select(pointer, nextPointer);
                if (Selection.Text.Length != 0)
                    return Selection.Text[0].ToString();
            }
            return "";
        }
        //void KeywordBackspaceProcdrue() {
        //    //TextPointer EndofContent = ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
        //    var targetPointer = GetPositionFromPoint(this.cursor).GetPositionAtOffset(0, LogicalDirection.Forward);
        //    var currentPointer = targetPointer;
        //    //if (currentPointer == null)
        //    //    return;
        //    string currentChar = GetCurrentChar(currentPointer, LogicalDirection.Backward);
        //    string word = string.Empty;
        //    while (currentChar != " " && currentChar != "") {
        //        currentPointer = currentPointer.GetNextInsertionPosition(LogicalDirection.Backward);
        //        currentChar = GetCurrentChar(currentPointer, LogicalDirection.Backward);
        //    }
        //    currentChar = GetCurrentChar(currentPointer, LogicalDirection.Forward);
        //    while (currentChar != " " && currentChar != "") {
        //        word += currentChar;
        //        currentPointer = currentPointer.GetNextInsertionPosition(LogicalDirection.Forward);
        //        currentChar = GetCurrentChar(currentPointer, LogicalDirection.Forward);
        //    }
        //    Selection.Select(currentPointer, targetPointer);
        //    if (keywordstore.ContainsKey(word))
        //        Selection.ApplyPropertyValue(Run.ForegroundProperty, keywordstore[word] ?? new SolidColorBrush(Colors.Black));
        //    var endc = GetPositionFromPoint(this.cursor).GetNextInsertionPosition(LogicalDirection.Forward);
        //    Selection.Select(endc, endc);
        //}
        string[] checkmarks = new string[] { " ", ",", ".", "+", "-", "*", "/", "=", "(", ")", "[", "]", "@", "!", ":", "?", "&", "#", "$", "`", "~", "|", "\\", ";", ">", "<" };
        string GetKeyword(ref TextPointer current, LogicalDirection dir) {
            var word = string.Empty;
            var currentchar = GetCurrentChar(current, dir);
            while (Regex.IsMatch(currentchar, @"[\w]")) {
                word += currentchar = GetCurrentChar(current, dir);
                current = current.GetNextInsertionPosition(dir);
            }
            current = current ?? this.ContentStart;
            if (dir == LogicalDirection.Backward) {
                var x = word.Reverse().ToArray();
                word = new string(x);
            }
            return word;
        }
        //
        //This method returns true if the RichTextBox is empty.
        public bool isRichTextBoxEmpty() {
            TextPointer startPointer = ContentStart.GetNextInsertionPosition(LogicalDirection.Forward);
            TextPointer endPointer = ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            if (startPointer.CompareTo(endPointer) == 0)
                return true;
            else
                return false;
        }
        //This method highlights the first word in the RichTextBox
        public void HighlightFirstWord(Panel p) {
            TextPointer StartofContent = this.ContentStart;
            TextPointer currentPointer = StartofContent.GetNextInsertionPosition(LogicalDirection.Forward);
            if (currentPointer == null)
                return;
            string currentChar = GetCurrentChar(currentPointer, LogicalDirection.Forward);
            while (currentChar != " " && currentChar != "") {
                currentPointer = currentPointer.GetNextInsertionPosition(LogicalDirection.Forward);
                currentChar = GetCurrentChar(currentPointer, LogicalDirection.Forward);
            }
            Rect StartRect = StartofContent.GetCharacterRect(LogicalDirection.Forward);
            Rect EndRect = currentPointer.GetCharacterRect(LogicalDirection.Forward);
            StartRect.Union(EndRect);
            CreateHighlightRectangle(StartRect, p);
        }
        private Rectangle CreateHighlightRectangle(Rect bounds, Panel panel) {
            Rectangle r = new Rectangle();
            r.Fill = new SolidColorBrush(Color.FromArgb(75, 0, 0, 200));
            r.Stroke = new SolidColorBrush(Color.FromArgb(230, 0, 0, 254));
            r.StrokeThickness = 1;
            r.Width = bounds.Width;
            r.Height = bounds.Height;
            Canvas.SetLeft(r, bounds.Left);
            Canvas.SetTop(r, bounds.Top + 41);
            panel.Children.Add(r);
            return r;
        }

        //void MyButton_Click(object sender, RoutedEventArgs e) {
        //    if (isRichTextBoxEmpty())
        //        MyTBl.Text = "RichTextBox is empty";
        //    else {
        //        HighlightFirstWord();
        //        UnderlineLastWord();
        //        MyTBl.Text = "";
        //    }
        //}
        #endregion
        int keywordmaxlen;
        Dictionary<string, Brush> keywordstore;
        public void AddKeyword(string key, Brush value) {
            keywordstore.Add(key, value);
            if (keywordstore.Count > 0) {
                var x = from item in keywordstore.Keys select item.Length;
                keywordmaxlen = x.Max();
            }
        }
        public IEnumerable<KeyValuePair<string, Brush>> Keywords {
            get {
                return from item in keywordstore select item;
            }
        }
        #region dp
        #endregion
    }
}
